package com.xsp.mybatisxmlsqlparser.multidatabase;


import cn.hutool.core.util.StrUtil;
import org.springframework.stereotype.Component;

/**
 * <p>
 * Oracle数据库函数
 * </p>
 *
 * @author kylin
 * @since 2020-03-04
 **/
@Component
public class OracleDbCharacteristics implements DbCharacteristics {

    @Override
    public String getColumnMark() {
        return "\"";
    }

    @Override
    public String getDefaultSchema() {
        return "";
    }

    @Override
    public DataBasesTypeEnum getDbType() {
        return DataBasesTypeEnum.ORACLE;
    }

    @Override
    public String sysdate() {
        return "sysdate";
    }

    @Override
    public String nvl(String a, String b) {
        return String.format("nvl(%s,%s)", a, b);
    }

    @Override
    public String nvlAlias(String s, String a) {
        return nvlAlias(s, a, s);
    }

    @Override
    public String nvlAlias(String s, String a, String alias) {
        return StrUtil.format("{} as {}", nvl(s, a), alias);
    }

    @Override
    public String nvl2(String s, String a, String b) {
        return String.format("nvl2(%s,%s,%s)", s, a, b);
    }

    @Override
    public String substr(String a, int b, int c) {
        return String.format("substr(%s,%d,%d)", a, b, c);
    }

    @Override
    public String toChar(String str, String format) {
        return StrUtil.format("to_char({},'{}')", str, convJavaDateTimeFormatToDb(format));
    }

    @Override
    public String toDate(String str, String format) {
        return StrUtil.format("to_date({},'{}')", str, convJavaDateTimeFormatToDb(format));
    }

    @Override
    public String toNumber(String str) {
        return String.format("to_number(%s)", str);
    }

    @Override
    public String listagg(String str) {
        return String.format("listagg(%s)", str);
    }

    @Override
    public String sysGuid() {
        return "SYS_GUID()";
    }

    /**
     * 按日加减日期
     *
     * @param field 字段名 字段对应的数据类型为date
     * @param days  正数为后移，负数前移
     * @return
     */
    @Override
    public String plusDays(String field, int days) {
        return StrUtil.format("({} + ({}))", field, days);
    }

    /**
     * 按日加减日期
     * <p>
     * 用于字符类型的字段，仅支持 yyyy-MM-dd格式的日期
     *
     * @param field 字段名或 文本日期，文本日期需要加单引号括住日期。 如A001044 或 '2001-01-01'
     * @param days  正数为后移，负数前移
     * @return
     */
    @Override
    public String plusDaysForVarchar(String field, int days) {
        return StrUtil.format("TO_CHAR((TO_DATE({},'yyyy-MM-dd') + ({})),'yyyy-MM-dd')", field, days);
    }

    /**
     * 按月加减日期
     *
     * @param field  字段名 字段对应的数据类型为date
     * @param months 正数为后移月份，负数前移
     * @return
     */
    @Override
    public String plusMonths(String field, int months) {
        return StrUtil.format("ADD_MONTHS({},{})", field, months);
    }

    /**
     * 按月加减日期
     * 正数为后移月份，负数前移
     * 用于字符类型的字段，format为类型
     *
     * @param field  字段名或 文本日期，文本日期需要加单引号括住日期。
     * @param months 正数为后移月份，负数前移
     * @param format 日期格式，使用java的日期格式，内部转换为不同数据库的格式化表达式  支持yyyy-MM-dd 或 yyyy-MM 两种日期格式
     * @return
     */
    @Override
    public String plusMonthsForVarcher(String field, int months, String format) {
        return StrUtil.format("TO_CHAR(ADD_MONTHS(TO_DATE({},'{}'), {}),'{}')", field, convJavaDateTimeFormatToDb(format), months, convJavaDateTimeFormatToDb(format));
    }

    /**
     * 计算两个日期差
     *
     * @param field1
     * @param field2
     * @param format 日期格式，使用java的日期格式，内部转换为不同数据库的格式化表达式
     * @return 返回 用于计算field1-field2的结果的sql字符串  field1>field2时 实际运算结果为正数
     */
    @Override
    public String daysForVarcher(String field1, String field2, String format) {
        return StrUtil.format("(TO_DATE({},'{}') - TO_DATE({},'{}'))", field1, format, field2, format);
    }

    public String convJavaDateTimeFormatToDb(String javaDateTimeFormat) {
        // yyyy-MM-dd
        String db = javaDateTimeFormat;
        db = db.replace("mm", "mi");
        db = db.replace("MM", "mm");
        db = db.replace("HH", "HH24");
        return db;
    }
}
